<?php

namespace app\command;

use app\model\AdminAgent;
use app\model\AgentDistribution;
use app\model\DistributionSetting;
use app\model\Order;
use app\model\OrderTeamCommissionLogModel;
use app\model\User;
use app\model\UserBalanceLog;
use app\service\AggregationService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use think\facade\Log;

class AggregationOrderBackstopCommand extends Command
{
	protected function configure()
	{
		$this->setName('aggregation-order-backstop')
			->setDescription('获取未完结佣金单列表');
	}

	/**
	 * @throws Exception
	 * @throws GuzzleException
	 * 每日凌晨1点执行，处理上一天的订单
	 */
	protected function execute(Input $input, Output $output)
	{
		$datetime = date('Y-m-d H:i:s');
		echo "{$datetime} do aggregation-order-backstop...\n";

		Log::init([
			'type'        => 'file',
			'apart_level' => ['error'],
			'level'       => ['error'],
			'path'        => app()->getRootPath() . "runtime/log/aggregation/",
			'max_files'   => 15,
		]);

		try {
			// 获取品牌不是微信小店的未结束订单
			$orderList = Order::field('id,brand_id,user_id,agent_id,order_id,status,commission_status,actual_commission,total')
				->whereRaw(sprintf('brand_id != %s', Order::BRAND_ID_WECHAT))
				->whereIn('status', Order::$statusWait)
				->where('commission_status', Order::COMMISSION_STATUS_WAIT)
				->select()
				->toArray();

			$userIds = array_column($orderList, 'user_id');
			// 查询用户列表
			$userList    = User::field('id,parent_user_id,agent_id,user_secret,level,rank,order_count')
				->whereIn('id', $userIds)
				->select()
				->toArray();
			$userListMap = array_column($userList, null, 'id');

			$orderIds = array_column($orderList, 'order_id');
			// 查询用户分佣记录
			$userBalanceList = UserBalanceLog::field('log_id,user_id,scene,order_id,money,status')->whereIn('order_id', $orderIds)->select()->toArray();

			$userBalanceListMap = [];
			foreach ($userBalanceList as $item) {
				$userBalanceListMap[$item['order_id']][] = $item;
			}

			foreach ($orderList as $item) {

				$userInfo        = $userListMap[$item['user_id']] ?? [];
				$userBalanceList = $userBalanceListMap[$item['order_id']] ?? [];

				// 根据未结束订单查询最新订单数据
				$instance = AggregationService::getInstance();
				$instance->initRequestParams([
					'order_sn' => $item['order_id'],
				]);
				$result = $instance->getOrderList();

				foreach ($result['data'] as $value) {
					$this->_handleUpdateOrderData($value, $item, $userInfo, $userBalanceList);
				}
			}
		} catch (Exception $e) {
			Log::error([
				'message' => $e->getMessage(),
				'line'    => $e->getLine(),
				'file'    => $e->getFile(),
				'trace'   => $e->getTraceAsString(),
			]);
		}
	}

	/**
	 * @param $item
	 * @param $orderInfo
	 * @param $userInfo
	 * @param $userBalanceList
	 * @return void
	 */
	private function _handleUpdateOrderData($item, $orderInfo, $userInfo, $userBalanceList): void
	{
		try {
			list($orderStatus, $commissionStatus) = $this->covertStatus($item['status']);
			// 查询订单状态是否相同
			if ($orderInfo['status'] == $orderStatus && $orderInfo['commission_status'] == $commissionStatus) {

				$isCompleted = true;
				foreach ($userBalanceList as $value) {
					if ($value['status'] != UserBalanceLog::STATUS_COMPLETED) {
						$isCompleted = false;
					}
				}

				if ($isCompleted === true) {
					return;
				}
			}

			// 订单状态更新信息
			$updateOrderData = [
				'status'            => $orderStatus,
				'commission_status' => $commissionStatus,
			];

			// 更新佣金状态 取消分佣
			$updateUserBalanceLog = [];
			foreach ($userBalanceList as $value) {
				if ($commissionStatus == Order::COMMISSION_STATUS_CANCEL) {
					$updateUserBalanceLog[] = [
						'log_id' => $value['log_id'],
						'status' => UserBalanceLog::STATUS_CANCEL,
					];
				}
			}

			// @tips 初始化订单时，分佣金额为0，获取订单状态时，订单金额不为0
			$commissionLog = [];
			if (floatval($item['jtk_share_fee']) > 0 && $orderInfo['actual_commission'] == 0) {

				$updateOrderData['actual_commission'] = $item['jtk_share_fee'] * 100;

				if ($userInfo) {
					//推客分享赚佣金
					$setting = AgentDistribution::getLevelInfo(0, $userInfo['level'], 1);

					$ratio      = isset($setting['ratio']) ? $setting['ratio'] / 100 : 0;            //推客分享赚佣金比例
					$type       = $setting['type'] ?? 0;                                              //分销类型，0：关闭，1：一级
					$ratioOne   = isset($setting['ratio_one']) ? $setting['ratio_one'] / 100 : 0; //一级分销比例
					$commission = round($item['jtk_share_fee'] * $ratio * 100);                 // 计算为分

					$oneCommission = 0;
					//如果开启分销，且用户有上级，则一级分销佣金 = 实际佣金 * 一级分销比例
					if ($type && $userInfo['parent_user_id'] > 0 && $ratioOne > 0) {
						$oneCommission = round($item['jtk_share_fee'] * $ratioOne * 100);
					}

					//利润 = 实际佣金 - 推客佣金
					$profit        = ($item['jtk_share_fee'] * 100) - $commission;
					$money         = round($commission / 100, 2);
					$commissionLog = [
						'user_id'      => $userInfo['id'],
						'from_user_id' => $userInfo['id'],
						'type'         => UserBalanceLog::TYPE_NEED_RECEIVE,
						'scene'        => UserBalanceLog::SCENE_SHARE_ORDER,
						'money'        => $money,
						'order_money'  => $item['pay_price'],
						'order_id'     => $item['order_sn'],
						'status'       => UserBalanceLog::STATUS_WAIT,
					];

					$updateOrderData['commission']     = $commission;
					$updateOrderData['one_commission'] = $oneCommission;
					$updateOrderData['profit']         = $profit;
				}
			}

			// 处理订单数据变更，处理分佣记录状态变更
			Db::transaction(function () use ($item, $orderInfo, $userInfo, $updateOrderData, $userBalanceList, $orderStatus, $commissionStatus, $updateUserBalanceLog, $commissionLog) {
				// 如果需要补发分佣
				if ($commissionLog) {
					$res               = UserBalanceLog::create($commissionLog);
					$userBalanceList[] = [
						'log_id'   => $res['id'],
						'user_id'  => $res['user_id'],
						'scene'    => $res['scene'],
						'order_id' => $res['order_id'],
						'money'    => $res['money'],
						'status'   => $res['status'],
					];
				}

				// 更新订单状态
				Order::where('order_id', $item['order_sn'])->update($updateOrderData);
				// 如果更新了订单的实际佣金金额
				if (isset($updateOrderData['actual_commission'])) {
					$orderInfo['actual_commission'] = $updateOrderData['actual_commission'];
				}

				// 更新分佣记录状态 取消分佣
				if (!empty($updateUserBalanceLog)) {
					foreach ($updateUserBalanceLog as $value) {
						UserBalanceLog::where('log_id', $value['log_id'])->update([
							'status' => $value['status'],
						]);
					}
				}

				// 状态已完成
				if ($orderStatus == 100 && $commissionStatus == 100) {
					$res = $this->updateUserBalance($orderInfo, $userInfo, $userBalanceList);
					if (!$res) {
						Log::error('更新用户余额失败：' . $orderInfo['order_id']);
						throw new Exception('更新用户余额失败：' . $orderInfo['order_id']);
					}
				}

				// 订单取消，则把分佣记录改为已取消状态
				if (in_array($orderStatus, [Order::STATUS_CANCEL, Order::STATUS_AUTO_CANCEL]) && $commissionStatus == Order::COMMISSION_STATUS_CANCEL) {
					UserBalanceLog::where('order_id', $item['order_sn'])->update([
						'status' => UserBalanceLog::STATUS_CANCEL,
					]);
				}
			});
		} catch (Exception $e) {
			Log::error([
				'message' => $e->getMessage(),
				'line'    => $e->getLine(),
				'file'    => $e->getFile(),
				'trace'   => $e->getTraceAsString(),
			]);
		}
	}


	/**
	 * @param array $orderInfo
	 * @param array $userInfo
	 * @param array $userBalanceList
	 * @return bool
	 */
	private function updateUserBalance(array $orderInfo, array $userInfo, array $userBalanceList): bool
	{

		// 用户不存在，则不发放佣金
		if (empty($userInfo)) {
			return true;
		}
		$userRes = User::where('id', $userInfo['id'])->update([
			'order_count' => $userInfo['order_count'] + 1,
		]);


		// 佣金奖励
		$userModel           = new User();
		$UserBalanceLogModel = new UserBalanceLog();

		$updateStatusLogIds = [];
		$teamUserBalanceLog = [];
		// 将分佣金额加到用户余额
		foreach ($userBalanceList as $value) {
			if ($value['scene'] == UserBalanceLog::SCENE_TEAM) {
				$teamUserBalanceLog = $value;
			}

			if ($value['status'] == UserBalanceLog::STATUS_WAIT) {
				$updateStatusLogIds[] = $value['log_id']; // 提交事物之前，会将主键id放入 id 字段，无论主键id是否叫做id
				$userModel->setIncMoney($value['user_id'], $value['money'] * 100);
				$userModel->setIncTotal($value['user_id'], $value['money'] * 100);
			}
		}

		// 给用户账户分佣后，将状态改为已结算
		$UserBalanceLogModel->whereIn('log_id', $updateStatusLogIds)->update([
			'status' => UserBalanceLog::STATUS_COMPLETED,
		]);

		// 团队奖励
		$team_ids      = explode('|', trim($userInfo['rank'], '|'));
		$team_ids      = array_reverse(array_slice(array_reverse($team_ids), 0, 9));
		$team_user_ids = $userModel->where('id', 'in', $team_ids)->where('level', '=', 3)->column('id');

		// 获取当前分佣队列开头的数据
		$firstOrderTeamCommissionId = OrderTeamCommissionLogModel::where('user_id', $orderInfo['user_id'])
			->where('level', 1)
			->order('id', 'desc')
			->value('id');
		// 获取当前分佣队列数据
		$orderTeamCommissionLogCount = OrderTeamCommissionLogModel::where('user_id', $orderInfo['user_id'])
			->where('id', '>=', $firstOrderTeamCommissionId)
			->count();
		$orderTeamCommissionLogCount = intval($orderTeamCommissionLogCount);
		$nextUserId                  = $team_ids[0];
		$level                       = 1;

		if ($orderTeamCommissionLogCount < count($team_ids)) {
			$nextUserId = $team_ids[$orderTeamCommissionLogCount];
			$level      = $orderTeamCommissionLogCount + 1;
		}
		if ($orderTeamCommissionLogCount == count($team_ids)) {
			$nextUserId = 0;
			$level      = $orderTeamCommissionLogCount + 1;
		}

		if (in_array($nextUserId, $team_user_ids) && empty($teamUserBalanceLog)) {
			$setting     = DistributionSetting::getLevelInfo(3, 1);
			$team_reward = round($setting['team_ratio'] * $orderInfo['actual_commission'] / 10000, 2);

			if ($team_reward > 0) {
				// 将金额发放到用户余额 && 累计总收益金额
				$userModel->setIncMoney($nextUserId, $team_reward * 100);
				$userModel->setIncTotal($nextUserId, $team_reward * 100);

				// 创建分佣记录信息
				UserBalanceLog::create([
					'user_id'      => $nextUserId,
					'from_user_id' => $userInfo['id'],
					'type'         => UserBalanceLog::TYPE_NEED_RECEIVE,
					'scene'        => UserBalanceLog::SCENE_TEAM,
					'money'        => $team_reward,
					'order_money'  => round($orderInfo['total'] / 100, 2),
					'order_id'     => $orderInfo['order_id'],
					'status'       => UserBalanceLog::STATUS_COMPLETED,
				]);

				// 添加订单团队分佣记录表 给系统分佣的话，也需要记录
				OrderTeamCommissionLogModel::create([
					'level'                     => $level,
					'user_id'                   => $orderInfo['user_id'],
					'order_id'                  => $orderInfo['order_id'],
					'commission_user_id'        => $nextUserId,
					'actual_commission_user_id' => in_array($nextUserId, $team_user_ids) ? $nextUserId : 0,
					'created_at'                => date('Y-m-d H:i:s'),
					'updated_at'                => date('Y-m-d H:i:s'),
				]);
			}
		}

		$agent_res = $shop_agent_res = true;
		if ($orderInfo['agent_id'] > 0) {
			$agent = AdminAgent::field('id, total_money, money')->where('id', $orderInfo['agent_id'])->find();
			//如果小店补贴佣金跟推客所属的合作商不一样，则代理商佣金需要减去小店补贴佣金
			$shop_agent = null;
			if ($orderInfo['agent_id'] != $orderInfo['agent_shop_agent']) {
				$agent_commission = $orderInfo['agent_commission'] - $orderInfo['agent_shop_commission'];
				$shop_agent       = AdminAgent::field('id, total_money, money')->where('id', $orderInfo['agent_shop_agent'])->find();
			} else {
				$agent_commission = $orderInfo['agent_commission'];
			}

			$agent_res = AdminAgent::where('id', $agent['id'])->update([
				'total_money' => $agent['total_money'] + $agent_commission,
				'money'       => $agent['money'] + $agent_commission,
			]);
			if ($shop_agent) {
				$shop_agent_res = AdminAgent::where('id', $orderInfo['agent_shop_agent'])->update([
					'total_money' => $shop_agent['total_money'] + $orderInfo['agent_shop_commission'],
					'money'       => $shop_agent['money'] + $orderInfo['agent_shop_commission'],
				]);
			}
		}
		if ($userRes && $agent_res && $shop_agent_res) {
			return true;
		}
		return false;
	}


	/**
	 * 转换状态
	 *
	 * @param int $status
	 * @return array
	 */
	private function covertStatus(int $status): array
	{
		// 订单统一状态，0：未付款 1：已付款 2：待结算 3：已结算 4：无效订单
		$orderStatus      = Order::STATUS_WAIT;
		$commissionStatus = Order::COMMISSION_STATUS_WAIT;
		// 订单状态，10：待付款，12：待收礼，20：待发货，21：部分发货，30：待收货，100：完成，200：全部商品售后之后，订单取消，250：未付款用户主动取消或超时未付款订单自动取消
		// 佣金状态，20：未结算，100：已结算，200：取消结算
		if ($status == 1) {
			$orderStatus = Order::STATUS_DELIVERY_WAIT; // 已付款待发货
		} else if ($status == 2) {
			$orderStatus = Order::STATUS_RECEIVE_WAIT; // 待收货(待结算)
		} else if ($status == 3) {
			$orderStatus      = Order::STATUS_COMPLETE;                 // 已结算(已完成)
			$commissionStatus = Order::COMMISSION_STATUS_COMPLETE; // 已结算
		} else if ($status == 4) {
			$commissionStatus = Order::COMMISSION_STATUS_CANCEL; // 无效订单(取消结算)
			$orderStatus      = Order::STATUS_AUTO_CANCEL;            // 无效订单(自动取消)
		}

		return [$orderStatus, $commissionStatus];
	}
}